﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Neat;
using Neat.Components;
using Neat.Mathematics;
using Neat.Graphics;

namespace Sectors
{
    class PerspectiveCamera
    {
        public float Fov;
        public float AspectRatio;
        public float NearPlaneDistance;
        public float FarPlaneDistance;
        public Vector3 Position;
        public Vector3 Target;
        public Vector3 Up;

        public PerspectiveCamera(
            float _fov, float _aspectRatio, float _near, float _far,
            Vector3 _position, Vector3 _target, Vector3 _up)
        {
            Fov = _fov;
            AspectRatio = _aspectRatio;
            NearPlaneDistance = _near;
            FarPlaneDistance = _far;
            Position = _position;
            Target = _target;
            Up = _up;
        }

        public void Switch(BasicEffect e)
        {
            e.Projection = Matrix.CreatePerspectiveFieldOfView(
                MathHelper.ToRadians(Fov),
                AspectRatio,
                NearPlaneDistance,
                FarPlaneDistance);
            e.View = Matrix.CreateLookAt(
                Position,
                Target,
                Up);
        }

        public virtual void Forward(float amount)
        {
            LineSegment ls = new LineSegment(Position.X, -Position.Z, Target.X, -Target.Z);
            ls.Forward(amount);
            Position.X = ls.StartPos.X;
            Position.Z = -ls.StartPos.Y;
            Target.X = ls.EndPos.X;
            Target.Z = -ls.EndPos.Y;
        }

        public virtual void Turn(float alpha)
        {
            LineSegment ls = new LineSegment(Position.X, -Position.Z, Target.X, -Target.Z);
            ls.Turn(alpha);
            Target.X = ls.EndPos.X;
            Target.Z = -ls.EndPos.Y;
        }

        public virtual void Strafe(float amount)
        {
            LineSegment ls = new LineSegment(Position.X, -Position.Z, Target.X, -Target.Z);
            ls.Strafe(amount);
            Position.X = ls.StartPos.X;
            Position.Z = -ls.StartPos.Y;
            Target.X = ls.EndPos.X;
            Target.Z = -ls.EndPos.Y;
        }

        public virtual void Elevate(float a)
        {
            Target.Y += a;
            Position.Y += a;
        }
    }

    class TopDownCamera : PerspectiveCamera
    {
        public TopDownCamera(
            float _fov, float _aspectRatio, float _near, float _far,
            Vector3 _position, Vector3 _target, Vector3 _up)
            : base(
                _fov, _aspectRatio, _near, _far,
                _position, _target, _up) { }

        public override void Turn(float alpha)
        {
            Up = Vector3.Transform(Up, Matrix.CreateRotationY(alpha));
            base.Turn(alpha);
        }
    }
}
